import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';

import '../extension/index.dart';
import 'common_log.dart';

mixin CommonLife {
  ///页面离开
  void pageLeave() {}

  ///页面重显
  void pageBack() {}

  ///页面关闭
  void pageClose() {}
}

abstract class CommonLifeState<T extends StatefulWidget> extends State<T>
    with WidgetsBindingObserver, LinkNavigatorObserver, CommonLife {
  late String _curRouteName = getRouteName();

  void _print(String msg) {
    Log.log('CommonLifeState : $runtimeType : $msg');
  }

  void _callPageLeave() {
    _print('_callPageLeave');
    pageLeave();
  }

  void _callPageBack() {
    _print('_callPageBack');
    pageBack();
  }

  void _callPageClose() {
    _print('_callPageClose');
    pageClose();
  }

  ///获取路由名字
  String getRouteName();

  //-----------------------state------------------------
  @override
  void initState() {
    super.initState();
    _print('initState');
    WidgetsBinding.instance.addObserver(this);
    NavigatorObserversOfCommonState.instance.addListener(this);
  }

  @override
  void dispose() {
    super.dispose();
    _print('dispose');
    WidgetsBinding.instance.removeObserver(this);
    NavigatorObserversOfCommonState.instance.removeListener(this);
  }

  @override
  void didUpdateWidget(covariant T oldWidget) {
    super.didUpdateWidget(oldWidget);
    _print('didUpdateWidget');
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _print('didChangeDependencies');
  }

  //-----------------------WidgetsBindingObserver------------------------

  @override
  void didChangeMetrics() {
    // _print('didChangeMetrics');
    super.didChangeMetrics();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    _print('didChangeAppLifecycleState: state = $state');
    if (getRouteName() != _curRouteName) return;
    if (AppLifecycleState.paused == state) {
      _callPageLeave();
    } else if (AppLifecycleState.resumed == state) {
      _callPageBack();
    }
  }

  @override
  void didChangeLocales(List<Locale>? locales) {
    _print('didChangeLocales');
  }

  @override
  void didChangePlatformBrightness() {
    _print('didChangePlatformBrightness');
  }

  @override
  void didChangeTextScaleFactor() {
    _print('didChangeTextScaleFactor');
  }

  //-----------------------NavigatorObserver------------------------

  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    String? routeName = route.settings.name;
    String? previousRouteName = previousRoute?.settings.name;
    String curRouteName = getRouteName();
    bool toNewPage = routeName.notEmpty;
    if (toNewPage) _curRouteName = routeName!;
    _print('$runtimeType,didPush, curRouteName = $curRouteName, previousRouteName = '
        '$previousRouteName, routeName = $routeName');
    if (previousRouteName == curRouteName && toNewPage) {
      _callPageLeave();
    }
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    String? routeName = route.settings.name;
    String? previousRouteName = previousRoute?.settings.name;
    String curRouteName = getRouteName();
    //理论上都会有值
    _curRouteName = previousRouteName ?? "/";
    _print('$runtimeType,didPop, curRouteName = $curRouteName, previousRouteName = '
        '$previousRouteName, routeName = $routeName');
    if (previousRouteName == curRouteName && routeName.notEmpty) {
      _callPageBack();
    } else if (routeName == curRouteName) {
      _callPageClose();
    }
  }
}

///用于监听路由变化
class NavigatorObserversOfCommonState extends NavigatorObserver {
  NavigatorObserversOfCommonState._();

  static final NavigatorObserversOfCommonState _instance = NavigatorObserversOfCommonState._();

  static NavigatorObserversOfCommonState get instance => _instance;

  final _listeners = <LinkNavigatorObserver>[];

  void addListener(LinkNavigatorObserver observer) {
    _listeners.add(observer);
  }

  void removeListener(LinkNavigatorObserver observer) {
    _listeners.remove(observer);
  }

  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    String? routeName = route.settings.name;
    String? previousRouteName = previousRoute?.settings.name;
    int size = _listeners.length;
    _print('didPush: route=$routeName,previousRoute=$previousRouteName,size=$size');
    for (var value in _listeners) {
      value.didPush(route, previousRoute);
    }
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    String? routeName = route.settings.name;
    String? previousRouteName = previousRoute?.settings.name;
    int size = _listeners.length;
    _print('didPop: route=$routeName,previousRoute=$previousRouteName,size=$size');
    for (var value in _listeners) {
      value.didPop(route, previousRoute);
    }
  }

  void _print(String msg) {
    Log.log('NavigatorObserversOfCommonState : $msg');
  }
}

mixin LinkNavigatorObserver {
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute);

  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute);
}

mixin CommonTickerProviderStateMixin implements TickerProvider {
  Set<Ticker>? _tickers;

  @override
  Ticker createTicker(TickerCallback onTick) {
    _tickers ??= <_WidgetTicker>{};
    final result = _WidgetTicker(onTick, this);
    _tickers!.add(result);
    return result;
  }

  void _removeTicker(_WidgetTicker ticker) {
    assert(_tickers != null);
    assert(_tickers!.contains(ticker));
    _tickers!.remove(ticker);
  }

  void didChangeDependencies(BuildContext context) {
    final muted = !TickerMode.of(context);
    if (_tickers != null) {
      for (final ticker in _tickers!) {
        ticker.muted = muted;
      }
    }
  }
}

class _WidgetTicker extends Ticker {
  _WidgetTicker(TickerCallback onTick, this._creator, {String? debugLabel}) : super(onTick, debugLabel: debugLabel);

  final CommonTickerProviderStateMixin _creator;

  @override
  void dispose() {
    _creator._removeTicker(this);
    super.dispose();
  }
}
